<template>
  <div class="app-container">
    <div class="filter-container">
      <el-input v-model="listQuery.query.name" class="filter-item" placeholder="套件名称" style="width: 200px;" @keyup.enter.native="filter" />
      <el-button class="filter-item" icon="el-icon-search" style="margin-left: 10px;" type="primary" @click="filter">搜索</el-button>
      <el-button class="filter-item" style="margin-left: 10px;" type="primary" @click="handleCreate">添加</el-button>
    </div>

    <el-table
      v-loading="listLoading"
      :data="list"
      element-loading-text="Loading"
      border
      fit
      highlight-current-row
      @sort-change="sortChange"
    >
      <el-table-column prop="id" align="center" label="id" width="95px" sortable>
        <template v-slot="{row}">
          {{ row.id }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="套件名称" prop="`name`" sortable>
        <template v-slot="{row}">
          {{ row.name }}
        </template>
      </el-table-column>
      <el-table-column prop="agentId" label="关联 Agent" align="center" width="120px">
        <template v-slot="{row}">
          {{ agentNameConvert(row.agentId) }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="运行环境" prop="env" width="120px">
        <template v-slot="{row}">
          {{ row.env }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="发送通知" prop="robotId" width="120px">
        <template v-slot="{row}">
          {{ robotNameConvert(row.robotId) }}
        </template>
      </el-table-column>
      <el-table-column label="更新时间" width="200px" align="center">
        <template v-slot="{row}">
          <span> {{ (row.updatedAt) | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }} </span>
        </template>
      </el-table-column>
      <el-table-column align="center" label="操作" width="370px">
        <template v-slot="{row, $index}">
          <el-button icon="el-icon-caret-right" type="success" size="mini" @click="runSuite(row)">执行</el-button>
          <el-button icon="el-icon-edit" type="primary" size="mini" @click="handleUpdate(row)">编辑</el-button>
          <el-button icon="el-icon-delete" type="danger" size="mini" @click="del(row, $index)">删除</el-button>
          <el-button icon="el-icon-tickets" type="button" size="mini" @click="showReport(row)">查看报告</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination v-show="listQuery.totalRecords>0" :limit.sync="listQuery.pageSize" :page.sync="listQuery.pageNum" :total="listQuery.totalRecords" @pagination="fetchData" />

    <!-- 性能测试套件 -->
    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="1200px" :close-on-click-modal="false">
      <el-form ref="dataForm" :rules="rules" :model="form" label-position="right" label-width="120px">
        <el-form-item label="套件名称" prop="name">
          <el-input v-model="form.name" placeholder="请输入套件名称" />
        </el-form-item>
        <el-row>
          <el-col :span="8">
            <el-form-item prop="agentId">
              <template slot="label">
                <span>关联 Agent</span>
                <el-tooltip placement="top">
                  <div slot="content" style="text-align: left">
                    1. 使用选择的 Agent 连接对应 load generators 执行压测脚本，并没有使用此 Agent 直接运行压测脚本<br>
                    2. 选择的 Agent 要跟所有压力机（load generators）在同一个子网，或可以访问到的外网 IP
                  </div><i class="el-icon-question" style="margin-left: 3px;" />
                </el-tooltip>
              </template>
              <el-select v-model="form.agentId" value-key="id" placeholder="请选择 关联 Agent" filterable>
                <el-option
                  v-for="item in agentOptions"
                  :key="item.id"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item prop="env">
              <template slot="label">
                <span>运行环境</span>
                <el-tooltip placement="top" content="根据选择的环境来使用对应环境的变量"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
              </template>
              <el-select v-model="form.env" value-key="id" placeholder="请选择 运行环境">
                <el-option
                  v-for="item in envOptions"
                  :key="item.id"
                  :label="item.envName"
                  :value="item.envName"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item>
              <template slot="label">
                <span>通知机器人</span>
                <el-tooltip placement="top" content="压测完成后会自动发送钉钉通知"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
              </template>
              <el-select v-model="form.robotId" clearable placeholder="请选择发送结果的机器人">
                <el-option
                  v-for="item in robotListData"
                  :key="item.id"
                  :disabled="item.disabled"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <div>
          <el-row>
            <el-col :span="12">
              <label style="font-size: 14px; color: #606266;">关联测试脚本</label>
            </el-col>
            <el-col :span="12">
              <div align="right" style="margin-bottom: 4px">
                <el-tooltip :open-delay="500" content="添加测试脚本" placement="top">
                  <el-button icon-class="skill" size="mini" type="primary" @click="handleInsertTestScript"><i class="el-icon-plus" /></el-button>
                </el-tooltip>
              </div>
            </el-col>
          </el-row>
          <el-table
            v-loading="listLoading"
            :data="form.testScripts"
            element-loading-text="Loading"
            border
            fit
            highlight-current-row
            @sort-change="sortChange"
          >
            <el-table-column prop="id" align="center" label="id" width="95px">
              <template v-slot="{row}">
                {{ row.id }}
              </template>
            </el-table-column>
            <el-table-column align="center" label="用例名称" prop="`name`">
              <template v-slot="{row}">
                {{ row.name }}
              </template>
            </el-table-column>
            <el-table-column prop="agentId" label="脚本类型" align="center" width="100px">
              <template v-slot="{row}">
                {{ getScriptTypeName(row.scriptType) }}
              </template>
            </el-table-column>
            <el-table-column align="center" label="压力机 / load generators" prop="env" width="300px">
              <template v-slot="{row}">
                <span v-for="element in row.generators" :key="element.id">
                  <el-tooltip :content="'id: ' + element.id + ',  系统: ' + getSystemTypeName(element.systemType) + ',  ip: ' + element.ip" placement="top">
                    <el-tag style="margin-left: 5px;">{{ element.desc }}</el-tag>
                  </el-tooltip>
                </span>
              </template>
            </el-table-column>
            <el-table-column align="center" label="测试场景" prop="robotId" width="200px">
              <template v-slot="{row}">
                日志模式: {{ getLogModeName(row.scenario.logMode) }} <br>
                控制模式: {{ getControlModeName(row.scenario.controlMode) }} <br>
                压测模式: {{ getLoadTestModeName(row.scenario.loadTestMode) }} <br>
              </template>
            </el-table-column>
            <el-table-column align="center" label="操作" width="180px">
              <template v-slot="{row, $index}">
                <el-button icon="el-icon-edit" type="primary" size="mini" @click="handleUpdateTestScript(row, $index)">编辑</el-button>
                <el-button icon="el-icon-delete" type="danger" size="mini" @click="delTestScript(row, $index)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogStatus==='create'?create():update()">确 定</el-button>
      </div>
    </el-dialog>

    <!-- 性能测试套件 - 添加一个测试脚本 -->
    <el-dialog :title="textMap[testScriptDialogStatus]" :visible.sync="testScriptDialogFormVisible" width="600px" :close-on-click-modal="false">
      <el-form ref="dataFormTestScript" :rules="testScriptRules" :model="formTestScript" label-position="right" label-width="125px">
        <el-form-item prop="name">
          <template slot="label">
            <span>测试脚本</span>
            <el-tooltip placement="top" content="需要执行的性能测试脚本"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
          </template>
          <span>
            <el-tooltip v-if="formTestScript.name" :content="'编写状态: ' + getEditStatusName(formTestScript.editStatus) + ',  脚本类型: ' + getScriptTypeName(formTestScript.scriptType) + ', 优先级: ' + getPriorityName(formTestScript.priority)" placement="top">
              <el-tag style="margin-left: 5px;">{{ formTestScript.name }}</el-tag>
            </el-tooltip>
            <el-button size="small" type="primary" style="margin-Left: 10px;" @click="getTestScriptFullData">选择脚本</el-button>
          </span>
        </el-form-item>
        <el-form-item prop="generators">
          <template slot="label">
            <span>压力机</span>
            <el-tooltip placement="top">
              <div slot="content" style="text-align: left">
                1. 会在选中的压力机上安装压测工具，并执行压测脚本<br>
                2. 当一台压力机不能满足压测需求时，可以选择多台压力机一起产生压力<br>
                3. 压力机工作在主从模式下 (不同工具名称不同，如：master/slave 或 master/worker 或 Controller/Load generator)<br>
                4. 第一个选中的压力机为主节点<br>
                5. 因为所有从节点都要连接主节点，所以主节点要可访问，并放开 5557、56287 端口
              </div><i class="el-icon-question" style="margin-left: 3px;" />
            </el-tooltip>
          </template>

          <el-select v-model="formTestScript.generators" value-key="id" style="width: 100%" clearable filterable multiple placeholder="请选择 压力机 / load generators">
            <el-option
              v-for="item in generatorOptions"
              :key="item.id"
              :label="item.desc"
              :value="item"
            />
          </el-select>
          <div style="font-size:12px;">主节点: <span v-if="formTestScript.generators && formTestScript.generators.length > 0" style="margin-left: 5px;">{{ formTestScript.generators[0].desc }}</span></div>
        </el-form-item>
        <el-divider>测试场景</el-divider>
        <el-form-item label="日志模式" prop="scenario.logMode">
          <el-select v-model="formTestScript.scenario.logMode" placeholder="请选择日志模式" style="margin-left: 2px;">
            <el-option v-for="item in logModeOptions" :key="item.value" :label="item.name" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item prop="scenario.controlMode">
          <template slot="label">
            <span>控制模式</span>
            <el-tooltip placement="top">
              <div slot="content" style="text-align: left">
                1. 集中模式：同时起压（同时启动，当设置的并发数全部结束后，再次启动进行施压）<br>
                2. 单独模式：单独起压（同时启动，当某个线程完成后，这个线程立即再次启动施压）
              </div><i class="el-icon-question" style="margin-left: 3px;" />
            </el-tooltip>
          </template>
          <el-select v-model="formTestScript.scenario.controlMode" placeholder="请选择控制模式" style="margin-left: 2px;">
            <el-option v-for="item in controlModeOptions" :key="item.value" :label="item.name" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item prop="scenario.loadTestMode">
          <template slot="label">
            <span>压测模式</span>
            <el-tooltip placement="top">
              <div slot="content" style="text-align: left; width: 500px;">
                <ol>
                  <li>并发模式：用于模拟多个用户同时操作，压力测试工具会模拟多个并发用户同时发送请求，以测试系统在高并发负载下的性能表现。这种模式适用于需要评估系统并发处理能力的场景，例如网站或应用程序的同时访问量很高的情况。</li>
                  <li>轮次模式：测试工具会执行多个测试轮次，每个轮次都包含一系列请求和操作，以评估系统在长时间运行、多次迭代下的性能和稳定性。这种模式适用于需要进行持久性能测试、负载测试和压力测试的场景，例如长时间运行的服务或系统。</li>
                  <li>阶梯模式：用于逐渐增加并发用户数量，模拟系统负载逐渐增加的情况。测试工具会逐渐增加并发用户的数量，以观察系统在负载逐步增加时的性能和稳定性表现。这种模式适用于模拟系统在用户数量逐渐增加时的负载情况，例如在系统投入使用后用户逐渐增多的情况。</li>
                  <li>错误率模式：用于测试系统在高错误率下的性能和稳定性。在该模式下，测试工具会模拟发送一定比例的错误请求，以评估系统在错误处理和容错能力方面的表现。这种模式适用于需要检验系统在异常或错误情况下的行为，例如测试系统在高错误率下的容错机制和错误处理能力。</li>
                  <li>响应时间模式：用于测量系统对请求的响应时间。在该模式下，测试工具会记录每个请求的响应时间，并生成相应的统计数据和报告，以评估系统的性能和响应能力。这种模式适用于需要关注系统的响应时间和性能指标的场景，例如对实时交互性能要求较高的应用程序或服务。</li>
                  <li>每秒应答数模式：用于测试系统在单位时间内能够处理的请求数量。在该模式下，测试工具会根据预设的每秒请求数量发送请求，以评估系统的负载能力和吞吐量。这种模式适用于需要测试系统在高负载下的性能和承载能力的场景，例如高流量的网站或服务。</li>
                </ol>
              </div><i class="el-icon-question" style="margin-left: 3px;" />
            </el-tooltip>
          </template>
          <el-select v-model="formTestScript.scenario.loadTestMode" placeholder="请选择压测模式" style="margin-left: 2px;" @change="handleChangeLoadTestMode($event)">
            <el-option v-for="item in loadTestModeOptions" :key="item.value" :label="item.name" :value="item.value" :disabled="item.disabled" />
          </el-select>
        </el-form-item>
        <!-- 并发模式 -->
        <div v-if="formTestScript.scenario.loadTestMode === getLoadTestModeValue('并发模式')">
          <el-form-item prop="scenario.content.duration">
            <template slot="label">
              <span>持续时长</span>
              <el-tooltip placement="top" content="压测的持续时间（单位：秒）"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.duration" :min="1" :max="999999" :controls="false" placeholder="单位: s" />
          </el-form-item>
          <el-form-item prop="scenario.content.count">
            <template slot="label">
              <span>并发数</span>
              <el-tooltip placement="top" content="同时发送请求的并发用户数量（单位：次）"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.count" :min="1" :max="99999" :controls="false" placeholder="单位: 次" />
          </el-form-item>
        </div>
        <!-- 轮次模式 -->
        <div v-else-if="formTestScript.scenario.loadTestMode === getLoadTestModeValue('轮次模式')">
          <el-form-item prop="scenario.content.rounds">
            <template slot="label">
              <span>轮次</span>
              <el-tooltip placement="top" content="在压测中执行的迭代次数（单位：次）"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.rounds" :min="1" :max="99999" :controls="false" placeholder="单位: 次" />
          </el-form-item>
          <el-form-item prop="scenario.content.count">
            <template slot="label">
              <span>并发数</span>
              <el-tooltip placement="top" content="同时发送请求的并发用户数量（单位：次）"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.count" :min="1" :max="99999" :controls="false" placeholder="单位: 次" />
          </el-form-item>
        </div>
        <!-- 阶梯模式、错误率模式、响应时间模式、每秒应答数模式 -->
        <div v-else-if="formTestScript.scenario.loadTestMode">
          <el-form-item prop="scenario.content.start">
            <template slot="label">
              <span>起始并发数</span>
              <el-tooltip placement="top" content="压测开始时的并发用户数量（单位：次）"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.start" :min="1" :max="99999" :controls="false" placeholder="单位: 次" />
          </el-form-item>
          <el-form-item prop="scenario.content.step">
            <template slot="label">
              <span>并发数步长</span>
              <el-tooltip placement="top" content="每个阶梯增加的并发用户数量。在此期间，会逐步增加并发用户，步长即为每次增加的用户数量（单位：次）"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.step" :min="1" :max="99999" :controls="false" placeholder="单位: 次" />
          </el-form-item>
          <el-form-item prop="scenario.content.stepDuration">
            <template slot="label">
              <span>步长持续时长</span>
              <el-tooltip placement="top" content="每个阶梯所持续的时间。在此期间，系统负载逐渐增加，直到达到下一个阶梯的并发用户数量（单位：秒）"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.stepDuration" :min="1" :max="999999" :controls="false" placeholder="单位: s" />
          </el-form-item>
          <el-form-item prop="scenario.content.max">
            <template slot="label">
              <span>最大并发数</span>
              <el-tooltip placement="top" content="允许的最大并发用户数量，当达到后不再增加并发用户数量（单位：次）"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.max" :min="1" :max="99999" :controls="false" placeholder="单位: 次" />
          </el-form-item>
          <el-form-item prop="scenario.content.duration">
            <template slot="label">
              <span>持续时长</span>
              <el-tooltip placement="top" content="压测的持续时间，包括所有阶梯的持续时长（单位：秒）"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.duration" :min="1" :max="999999" :controls="false" placeholder="单位: s" />
          </el-form-item>
          <!-- 错误率模式 -->
          <el-form-item v-if="formTestScript.scenario.loadTestMode === getLoadTestModeValue('错误率模式')" prop="scenario.content.errorRate">
            <template slot="label">
              <span>错误率</span>
              <el-tooltip placement="top">
                <div slot="content" style="text-align: left;">
                  1. 当某一接口的错误率，大于该值后则自动停止<br>
                  2. 如果到达最大并发数后，错误率仍没有超过该值，则继续运行到结束
                </div><i class="el-icon-question" style="margin-left: 3px;" />
              </el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.errorRate" :min="0" :max="100" :controls="false" placeholder="单位: %" />
          </el-form-item>
          <!-- 响应时间模式 -->
          <el-form-item v-else-if="formTestScript.scenario.loadTestMode === getLoadTestModeValue('响应时间模式')" prop="scenario.content.responseTime">
            <template slot="label">
              <span>响应时间</span>
              <el-tooltip placement="top">
                <div slot="content" style="text-align: left;">
                  1. 当某一接口响应时间，大于该值后则并发数不再增加，并持续运行到结束<br>
                  2. 如果到达最大并发数后仍未达到该值，则并发数不再增加，并持续运行到结束
                </div><i class="el-icon-question" style="margin-left: 3px;" />
              </el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.responseTime" :min="1" :max="999999" :controls="false" placeholder="单位: ms" />
          </el-form-item>
          <!-- 每秒应答数模式 -->
          <el-form-item v-else-if="formTestScript.scenario.loadTestMode === getLoadTestModeValue('每秒应答数模式')" prop="scenario.content.throughput">
            <template slot="label">
              <span>每秒应答数</span>
              <el-tooltip placement="top" content="每秒应答数大于此值，那么并发数会直接增加到最大，然后按照持续时长运行对应时间"><i class="el-icon-question" style="margin-left: 3px;" /></el-tooltip>
            </template>
            <el-input-number v-model="formTestScript.scenario.content.throughput" :min="1" :max="99999999" :controls="false" placeholder="单位: 次" />
          </el-form-item>
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="testScriptDialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="testScriptDialogStatus==='create'?createTestScript():updateTestScript()">确 定</el-button>
      </div>
    </el-dialog>

    <!-- 性能测试套件 - 添加一个测试脚本 - 选择脚本 -->
    <el-dialog title="选择脚本" :visible.sync="selectTestScriptDialogFormVisible" width="700px" :close-on-click-modal="false">
      <div style="overflow-y: scroll; overflow-x: hidden; height: 400px; border:solid 1px #dfe4ed;">
        <tree-component
          ref="treeComponent"
          catalog-label="目录"
          :tree-data="fullDate"
          readonly
          style="width: 99%;"
          @choose-element="chooseElement"
        />
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button @click="selectTestScriptDialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="selectTestScript()">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { list, create, update, del, findById, run } from '@/api/performance_test/perf_test_suite'
import { selectById as testScriptSelectById } from '@/api/performance_test/test_script.js'
import Pagination from '@/components/Pagination'
import TreeComponent from '@/components/functional_test/Tree/index.vue'
import { listAll as robotList } from '@/api/project/robot'
import { selectAll as agent_selectAll } from '@/api/functional_test/agent'
import { listAll as generator_selectAll } from '@/api/performance_test/generator'
import { findList as env_selectAll } from '@/api/functional_test/env_param'
import { getScriptTypeName } from '@/enum/scriptType'
import { getSystemTypeName } from '@/enum/systemType.js'
import { getPriorityName } from '@/enum/priority'
import { getEditStatusName } from '@/enum/editStatus'
import { loadTestModeOptions, getLoadTestModeValue, getLoadTestModeName } from '@/enum/loadTestMode'
import { logModeOptions, getLogModeName } from '@/enum/logMode'
import { controlModeOptions, getControlModeName } from '@/enum/controlMode'
import { deepClone } from '@/utils'
import { listTree as getTestScriptFullData } from '@/api/functional_test/catalog'

export default {
  components: { Pagination, TreeComponent },
  data() {
    return {
      loadTestModeOptions,
      logModeOptions,
      controlModeOptions,
      projectId: this.$store.getters.projectId,
      list: null,
      listLoading: true,
      listQuery: {
        pageNum: 1,
        pageSize: 10,
        totalRecords: 0,
        orders: undefined,
        query: {
          projectId: this.$store.getters.projectId
        }
      },
      form: {
        projectId: this.projectId,
        id: undefined,
        testScripts: []
      },
      formTestScript: {
        projectId: this.projectId,
        id: undefined,
        scenario: {
          content: {},
          logMode: 1,
          controlMode: 2,
          loadTestMode: 1
        }
      },
      dialogFormVisible: false,
      testScriptDialogFormVisible: false,
      selectTestScriptDialogFormVisible: false,
      selectTestScriptId: 0, // 记录 性能测试套件 - 添加一个测试脚本 - 选择脚本 的 ID
      formLabelWidth: '120px',
      dialogStatus: '',
      testScriptDialogStatus: '',
      textMap: {
        update: '修改',
        create: '添加'
      },
      envOptions: [],
      robotListData: [],
      agentOptions: [],
      generatorOptions: [],
      fullDate: [],
      treeData: {
        type: 5, // 元素类型（功能测试用例 CatalogType=1，接口测试用例 CatalogType=3, 公共步骤 CatalogType=4，性能测试脚本 CatalogType=5）
        parentId: 0,
        caseType: 5,
        projectId: this.$store.getters.projectId
      },
      rules: {
        name: [
          { required: true, message: '请输入 套件名称', trigger: 'change' },
          { max: 50, message: '套件名称 长度不能超过 50 个字符', trigger: 'blur' }
        ],
        agentId: [
          { required: true, message: '请选择 关联 Agent', trigger: 'change' }
        ],
        env: [
          { required: true, message: '请选择 运行环境', trigger: 'change' }
        ]
      },
      testScriptRules: {
        generators: [
          { required: true, message: '请选择 压力机', trigger: 'blur' }
        ],
        'scenario.logMode': [
          { required: true, message: '请选择 日志模式', trigger: 'blur' }
        ],
        'scenario.controlMode': [
          { required: true, message: '请选择 控制模式', trigger: 'blur' }
        ],
        'scenario.loadTestMode': [
          { required: true, message: '请选择 压测模式', trigger: 'blur' }
        ],
        'scenario.content.duration': [
          { required: true, message: '请输入 持续时长', trigger: 'blur' }
        ],
        'scenario.content.count': [
          { required: true, message: '请输入 并发数', trigger: 'blur' }
        ],
        'scenario.content.rounds': [
          { required: true, message: '请输入 轮次', trigger: 'blur' }
        ],
        'scenario.content.start': [
          { required: true, message: '请输入 起始并发数', trigger: 'blur' }
        ],
        'scenario.content.step': [
          { required: true, message: '请输入 并发数步长', trigger: 'blur' }
        ],
        'scenario.content.stepDuration': [
          { required: true, message: '请输入 步长持续时长', trigger: 'blur' }
        ],
        'scenario.content.max': [
          { required: true, message: '请输入 最大并发数', trigger: 'blur' }
        ],
        'scenario.content.errorRate': [
          { required: true, message: '请输入 错误率', trigger: 'blur' }
        ],
        'scenario.content.responseTime': [
          { required: true, message: '请输入 响应时间', trigger: 'blur' }
        ],
        'scenario.content.throughput': [
          { required: true, message: '请输入 每秒应答数', trigger: 'blur' }
        ]
      }
    }
  },
  created() {
    this.fetchData()
  },
  methods: {
    getScriptTypeName,
    getSystemTypeName,
    getPriorityName,
    getEditStatusName,
    getLogModeName,
    getControlModeName,
    getLoadTestModeValue,
    getLoadTestModeName,
    fetchData() {
      this.listLoading = true
      list(this.listQuery).then(response => {
        this.list = response.data.list
        this.listQuery.totalRecords = response.data.page.totalRecords
        this.listLoading = false
      })

      this.loadRobotList()
      this.agent_selectAll()
      this.env_selectAll()
      this.generator_selectAll()
    },
    filter() {
      this.listQuery.pageNum = 1
      this.fetchData()
    },
    // 创建
    create() {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          const tempForm = deepClone(this.form)

          // 遍历 testScripts 将 scenario.content json 对象转为字符串
          if (tempForm.testScripts) {
            for (const testScript of tempForm.testScripts) {
              if (testScript.scenario && testScript.scenario.content) {
                testScript.scenario.content = JSON.stringify(testScript.scenario.content)
              }
            }
          }

          create(tempForm).then(() => {
            this.dialogFormVisible = false
            this.$message({ message: '添加成功!', type: 'success' })
            this.fetchData()
          })
        }
      })
    },
    // 修改
    update() {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          const tempForm = deepClone(this.form)

          // 遍历 testScripts 将 scenario.content json 对象转为字符串
          if (tempForm.testScripts) {
            for (const testScript of tempForm.testScripts) {
              if (testScript.scenario && testScript.scenario.content && typeof testScript.scenario.content === 'object') {
                testScript.scenario.content = JSON.stringify(testScript.scenario.content)
              }
            }
          }

          update(tempForm).then(() => {
            const index = this.list.findIndex(v => v.id === this.form.id)
            this.fetchData()
            this.list.splice(index, 1, this.form)
            this.dialogFormVisible = false
            this.$message({ message: '修改成功!', type: 'success' })
          })
        }
      })
    },
    resetForm() {
      this.form = {
        projectId: this.projectId,
        id: undefined,
        testScripts: []
      }
    },
    // 点击添加按钮
    handleCreate() {
      this.resetForm()
      this.dialogStatus = 'create'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    // 点击修改按钮
    handleUpdate(row) {
      findById(row.id).then(response => {
        this.listLoading = false
        this.form = response.data
        if (this.form.robotId === 0) {
          this.form.robotId = ''
        }
        this.dialogStatus = 'update'
        this.dialogFormVisible = true
        this.$nextTick(() => {
          this.$refs['dataForm'].clearValidate()
        })
      })
    },
    // 删除
    del(row, index) {
      this.$confirm('是否删除此记录?', '提示', {
        confirmButtonText: '是',
        cancelButtonText: '否',
        type: 'warning'
      }).then(() => {
        del(row.id).then(response => {
          this.$message({ message: '删除成功!', type: 'success' })
          this.list.splice(index, 1)
        })
      })
    },
    // 点击 table 排序
    sortChange(column) {
      this.listQuery.orders = [{
        column: column.prop,
        asc: column.order === 'ascending'
      }]
      this.fetchData()
    },
    // 查询钉钉机器人列表
    loadRobotList() {
      this.listLoading = true
      robotList(this.projectId).then(response => {
        this.robotListData = response.data
        this.listLoading = false
      })
    },
    // 机器人 ID 转 name
    robotNameConvert(robotId) {
      let robotName = ''
      this.robotListData.forEach(item => {
        if (item.id === robotId) {
          robotName = item.name
          return
        }
      })
      return robotName
    },
    // 查询所有 agent
    agent_selectAll() {
      agent_selectAll().then(response => {
        this.agentOptions = response.data
      })
    },
    // agent ID 转 name
    agentNameConvert(agentId) {
      let robotName = ''
      this.agentOptions.forEach(item => {
        if (item.id === agentId) {
          robotName = item.name
          return
        }
      })
      return robotName
    },
    env_selectAll() {
      env_selectAll({ projectId: this.projectId }).then(response => {
        this.envOptions = response.data
      })
    },
    // 查询所有 generator
    generator_selectAll() {
      generator_selectAll(this.projectId).then(response => {
        this.generatorOptions = response.data
      })
    },
    resetFormTestScript() {
      this.formTestScript = {
        projectId: this.projectId,
        id: undefined,
        scenario: {
          content: {},
          logMode: 1,
          controlMode: 2,
          loadTestMode: 1
        }
      }
    },
    // 点击添加测试脚本
    handleInsertTestScript() {
      this.resetFormTestScript()
      this.testScriptDialogStatus = 'create'
      this.testScriptDialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataFormTestScript'].clearValidate()
      })
    },
    // 点击关联脚本列表中的修改按钮
    handleUpdateTestScript(row, index) {
      this.testScriptIndex = index
      this.formTestScript = Object.assign({}, row) // 复制行数据

      // 将 scenario.content json 字符串转为对象
      if (this.formTestScript && this.formTestScript.scenario && (typeof this.formTestScript.scenario.content === 'string' || this.formTestScript.scenario.content instanceof String)) {
        this.formTestScript.scenario.content = JSON.parse(this.formTestScript.scenario.content)
      }

      this.testScriptDialogStatus = 'update'
      this.testScriptDialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataFormTestScript'].clearValidate()
      })
    },
    // 创建 测试脚本
    createTestScript() {
      if (!this.formTestScript || !this.formTestScript.name || this.formTestScript.name === '') {
        this.$message({ message: '请选择测试脚本后，再点击 确定 按钮！', type: 'error' })
        return
      }
      this.$refs['dataFormTestScript'].validate((valid) => {
        if (valid) {
          this.form.testScripts.push(this.formTestScript)
          this.testScriptDialogFormVisible = false
        }
      })
    },
    // 修改 测试脚本
    updateTestScript() {
      if (!this.formTestScript || !this.formTestScript.name || this.formTestScript.name === '') {
        this.$message({ message: '请选择测试脚本后，再点击 确定 按钮！', type: 'error' })
        return
      }
      this.$refs['dataFormTestScript'].validate((valid) => {
        if (valid) {
          this.form.testScripts.splice(this.testScriptIndex, 1, this.formTestScript)
          this.testScriptDialogFormVisible = false
        }
      })
    },
    // 删除 测试脚本
    delTestScript(row, index) {
      this.$confirm('是否删除此记录?', '提示', {
        confirmButtonText: '是',
        cancelButtonText: '否',
        type: 'warning'
      }).then(() => {
        this.form.testScripts.splice(index, 1)
      })
    },
    // 选择 压测模式
    handleChangeLoadTestMode(event) {
      this.formTestScript.scenario.content = {}
    },
    // 递归去掉已选中的测试脚本
    recursiveRemoveSelected(fullTree, selectedList) {
      const fullTrees = []
      for (const ft of fullTree.children) {
        if (ft.isCatalog) {
          ft.children = this.recursiveRemoveSelected(ft, selectedList)
        }

        if (this.unselected(ft.id, selectedList)) {
          fullTrees.push(ft)
        }
      }
      return fullTrees
    },
    // 递归去掉已选中的测试脚本中 - 判断未选中这个测试脚本
    unselected(id, selectedList) {
      if (selectedList) {
        for (const testScript of selectedList) {
          if (testScript.id === id) {
            return false
          }
        }
      }
      return true
    },
    // 点击 选择脚本 按钮
    getTestScriptFullData() {
      getTestScriptFullData(this.treeData).then(response => {
        const fullTrees = []
        for (const element of response.data) {
          if (element.isCatalog) {
            element.children = this.recursiveRemoveSelected(element, this.form.testScripts)
            fullTrees.push(element)
          } else {
            if (this.unselected(element.id, this.form.testScripts)) {
              fullTrees.push(element)
            }
          }
        }
        this.fullDate = fullTrees

        this.$nextTick(() => {
          this.selectTestScriptId = 0
          this.selectTestScriptDialogFormVisible = true
        })
      })
    },
    // tree：点击一个元素后调用此方法
    chooseElement(id) {
      this.selectTestScriptId = id
    },
    // 点击 性能测试套件 - 添加一个测试脚本 - 选择脚本 弹窗的确定按钮
    selectTestScript() {
      if (this.selectTestScriptId === 0) {
        this.$message({ message: '请选择一个测试脚本后，再点击 确定 按钮！', type: 'error' })
        return
      }

      testScriptSelectById(this.selectTestScriptId).then(response => {
        this.formTestScript.id = response.data.id
        this.formTestScript.catalogId = response.data.catalogId
        this.formTestScript.scriptType = response.data.scriptType
        this.formTestScript.editStatus = response.data.editStatus
        this.formTestScript.priority = response.data.priority
        this.formTestScript.name = response.data.name

        this.selectTestScriptDialogFormVisible = false
      })
    },
    // 点击执行按钮
    runSuite(row) {
      run(row.projectId, row.id).then(response => {
        this.$message({ message: '运行成功!', type: 'success' })
      })
    },
    showReport(row) {
      this.$router.push({
        path: '/performance_test/test_results',
        query: {
          suiteId: row.id,
          projectId: row.projectId
        }
      })
    }
  }
}
</script>
